#ifndef DATA_LINK_H_
#define DATA_LINK_H_

// Serial Ports
#define TTYS0 0
#define TTYS0_VALUE "/dev/ttyS0"
#define TTYS1 1
#define TTYS1_VALUE "/dev/ttyS1"

// Debugging
#define DEBUG 0
#define DEBUG_PRINT_BUFFER(buf, len) {int i; for(i = 0; i < len; ++i) printf( (i < 9 ? "0x%x|" : "%c") , buf[i]); printf("\n\n");}

// Frame Declarations
#define MAX_CFRAME 5
#define MAX_FRAME_SIZE 756
#define DFRAME_HEADER_SIZE 4
#define DFRAME_FOOTER_SIZE 2

#define FLAG 0x7E
#define ADDRESS 0x03
#define C_SET 0x03
#define C_DISC 0x0D
#define C_UA 0x07
#define C_RR0 (0x01 | (0x00 << 5))
#define C_RR1 (0x01 | (0x01 << 5))
#define C_RR(r) (0x01 | (r << 5))
#define C_REJ0 (0x05 | (0x00 << 5))
#define C_REJ1 (0x05 | (0x01 << 5))
#define C_REJ(r) (0x05 | (r << 5))
#define C_S(r) (r << 1)
#define C_S0 C_S(0)
#define C_S1 C_S(1)
#define BCC(c) (ADDRESS ^ c)

#define ESC 0x7d

#define TIME_OUT 2
#define MAX_TIMEOUTS 10

#define MAX_READS_FILE 3
#define MAX_TRIES 3

#define FRAME_RD_ERROR -1
#define FRAME_READ 0
#define FRAME_RD_TIMEOUT 1


 // State Machine Declarations
#define NULL_STATE -1
#define F1_STATE 0
#define A_STATE 1
#define C_STATE 2
#define BCC_STATE 3
#define F2_STATE 4

#define N_STATES 6

#define SENDER 0
#define RECEIVER 1 

extern char cframe_set[];
extern char cframe_ua[];
extern char cframe_disc[];
extern char cframe_rr_zero[];
extern char cframe_rr_one[];
extern char cframe_rej_zero[];
extern char cframe_rej_one[];
extern char dframe_header_zero[];
extern char dframe_header_one[];

extern int _flag;
extern int _rr;

extern int time_out;
extern int max_timeouts;

int open_connection(int port_no);
int close_connection(int port_no);
void write_cframe(int fd, char control);
int write_dframe(int fd, char* packet, int p_len);
int read_cframe(int fd, char cframe[]);
int read_dframe(int fd, char* buf);

char * get_cframe_rr();
char * next_cframe_rr();

#endif // DATA_LINK_H_
